<?php
	class MessageHandler
	{
		// Membervariables
		private $_con = null;
		private $_messageView = null;
		private $_userHandler = null;
		
		// Constants
		const MESSAGENOTMARKEDASREAD = "The message's readstatus was not set to 1.";
		const TOFIELDCONTAINSHTML = "The to field contained HTML check time and ip.";
		const TOPICCONTAINSHTML = "The topic contained HTML check time and ip.";
		const CONTENTCONTAINSHTML = "The content contained HTML check time and ip.";
		const TOPICWASTOLONG = "The topic input was to long, max length: 128";
		const USERNAMEWASTOLONG = "The username input was to long, max length: 32";
		const USERDIDNOTEXIST = "No user with that name exists.";
		const ANERROROCCURED = "An error has occured.";
		const TOPICWASEMPTY = "Please enter a topic.";
		const RECIEVERWASEMPTY = "Please enter a reciever.";
		const MESSAGESENT = "Message has been sent.";
		const MESSAGECOULDNTBESENT = "The message could not be sent, please try again later.";
		const MESSAGEFAILEDTOSEND = "The message could not be sent check the errorlog for sql or database errors.";

		public function __construct(DBConnection $con, $messageView, $userHandler)
		{
			$this->_con = $con;
			$this->_messageView = $messageView;
			$this->_userHandler = $userHandler;
		}
		
		// Returns a message object.
		public function GenerateMessage(\User $user)
		{
			$message = new Message;
			
			// Fill in all the data.
			$message->messageid = $this->GenerateMessageId();
			$message->topic = $this->_messageView->GetTopic();
			$message->senderusername = $user->username;
			$message->senderid = $user->id;
			$message->recieverusername = $this->_messageView->GetReciever();
			$message->recieverid = $this->_messageView->GetRecieverId();
			$message->messagecontent = $this->_messageView->GetContent();
			$date = getdate();
			$date = date("Y-m-d H:i:s");
			$message->senddate = $date;
			$message->readstatus = 0;
	
			return $message;
		}
		
		// Generates a new unique messageid.
		private function GenerateMessageId()
		{
			// Get a list of all the messages.
			$messageList = $this->GetMessageList();
			$newId = 0;
			
			foreach ($messageList as $message)
			{
				if ($newId == $message->messageid)
				{
					$newId++;
				}
				else 
				{
					return $newId;
				}
			}
			
			return $newId;
		}
		
		// Returns all the messages for a specific member from the database.
		public function GetMemberMessageList(\User $user)
		{
			$classname = "Message";
			$sql = "SELECT * FROM messages WHERE recieverid = ?";
			
			$stmt = $this->_con->Prepare($sql);
			
			$stmt->bind_param("i", $user->id);
			
			$arr = $this->_con->RunAndFetchObjects($stmt, $classname, "messageid");
			
			return $arr;
		}
		
		// Returns a message-object.
		public function GetMessage($messageid)
		{
			$classname = "Message";
			$sql = "SELECT * FROM messages WHERE messageid = ?";
			
			$stmt = $this->_con->Prepare($sql);
			
			$stmt->bind_param("i", $messageid);
			
			$arr = $this->_con->RunAndFetchObjects($stmt, $classname, "messageid");
			
			if (count($arr) == 1)
			{
				return $arr[$messageid];
			}
			else
			{
				return null;
			}	
		}
		
		// Returns all the messages in the database
		public function GetMessageList()
		{
			$classname = "Message";
			$sql = "SELECT * FROM messages";
			
			$stmt = $this->_con->Prepare($sql);
			
			$arr = $this->_con->RunAndFetchObjects($stmt, $classname, "messageid");
			
			return $arr;
		}
		
		// Marks a message as read.
		public function MarkAMessageAsRead($messageid)
		{
			$sql = "UPDATE `messages` SET `readstatus` = 1 WHERE `messageid`= ?";
			$stmt = $this->_con->Prepare($sql);
				
			$stmt->bind_param("i", $messageid);
				
			$stmt->execute();
				
			$stmt->close();
				
			// Check if the messages status was actually changed.
			$message = $this->GetMessage($messageid);
			if ($message->readstatus != 1)
			{
				Log::LogError("", $this::MESSAGENOTMARKEDASREAD);
			}
		}
		
		// Check wether the user has any unread messages.
		public function DoesUserHaveNewMessages(\User $user)
		{
			$messageList = $this->GetMemberMessageList($user);
			
			foreach ($messageList as $message)
			{
				if ($message->readstatus == 0)
				{
					return true;
				}
			}
			return false;
		}
		
		// Returns the number of unread messages for the given user.
		public function GetNumberOfNewMessages(\User $user)
		{
			$count = 0;
			// Get the list of messages.
			$messageList = $this->GetMemberMessageList($user);
			
			// Check the readstatus of all messages in the list.
			foreach ($messageList as $message)
			{
				if ($message->readstatus == 0)
				{
					$count++;
				}
			}
			
			return $count;
		}		
		
		// Saves the mssage to the database.
		public function SaveMessage(\Message $message)
		{
			$sql = "INSERT INTO `messages` (`messageid`, `topic`, `senderusername`, `senderid`, `recieverusername`, `recieverid`, `messagecontent`, `senddate`, `readstatus`) VALUES" .
			"(?,?,?,?,?,?,?,?,?)";
				
			$stmt = $this->_con->Prepare($sql);
				
			$stmt->bind_param("issisissi", $message->messageid, $message->topic, $message->senderusername, $message->senderid, $message->recieverusername, $message->recieverid, $message->messagecontent, $message->senddate, $message->readstatus);
				
			$stmt->execute();
				
			$stmt->close();
			
			// If the message was added to the database
			if ($this->GetMessage($message->messageid) != null)
			{
				Log::LogMessage($this::MESSAGESENT);
			}
			else 
			{
				Log::LogError($this::MESSAGECOULDNTBESENT, $this::MESSAGEFAILEDTOSEND);
			}
		}
		
		// Returns wether the message contained any errors.
		public function MessageDidNotCotainErrors()
		{
			$validation = new Validation();
			$topic = $this->_messageView->GetTopic();
			$to = $this->_messageView->GetReciever();
			$content = $this->_messageView->GetContent();
			$comparisonTopic = "";
			$comparisonTo = "";
			$comparisonContent = "";
			
			// Check if the topic was empty
			if ($validation->IsInputEmpty($topic) == true)
			{
				Log::LogMessage($this::TOPICWASEMPTY);
				return false;
			}			
			
			// Check if the topic contains html.
			$comparisonTopic = $validation->StripAll($topic);
			
			if ($comparisonTopic != $topic)
			{
				Log::LogError($this::ANERROROCCURED, $this::TOPICCONTAINSHTML);
				return false;
			}
			
			// Check the topics length.
			if (strlen($topic) > 128)
			{
				Log::LogMessage($this::TOPICWASTOLONG);
				return false;
			}
			
			// Check if the reciever was empty.
			if ($validation->IsInputEmpty($to) == true)
			{
				Log::LogMessage($this::RECIEVERWASEMPTY);
				return false;
			}
			
			// Check if the reciever contains html
			$comparisonTo = $validation->StripAll($to);
			
			if ($comparisonTo != $to)
			{
				Log::LogError($this::ANERROROCCURED, $this::TOFIELDCONTAINSHTML);
				return false;
			}
			
			// Check the length of the username
			if (strlen($to) > 32)
			{
				Log::LogMessage($this::USERNAMEWASTOLONG);
				return false;
			}
			
			// Check if the user exists
			if ($this->_userHandler->GetUser($to) == null)
			{
				Log::LogMessage($this::USERDIDNOTEXIST);
				return false;
			}
			
			// Check if the content contains html
			$comparisonContent = $validation->StripAll($content);
			
			if ($comparisonContent != $content)
			{
				Log::LogError($this::ANERROROCCURED, $this::CONTENTCONTAINSHTML);
				return false;
			}
			
			return true;
		}
	}